package top.chmin.project.cloud.code.java.model;

import org.springframework.stereotype.Component;
import top.chmin.project.cloud.code.BuildData2;
import top.chmin.project.cloud.code.Builder2;

/**
 * chmin
 * 2024/1/11 8:44
 * cloud-builder
 */
@Component
public class Model2Builder implements Builder2 {
    @Override
    public void build(BuildData2 buildData) {
        String source = """
                package top.chmin.project.cloud.#t.moduleName;
                                
                /**
                 * chmin
                 * #s.now
                 * cloud-code
                 */
                @Getter
                @Setter
                @Accessors(chain = true)
                public class #t.modelName extends Model {
                /* append $modelField2Appender$ */
                                
                    public #t.modelNameModelCondition forInsert() {
                        return new #t.modelNameModelCondition().forInsert();
                    }
                                
                    public #t.modelNameModelCondition forUpdate() {
                        return new #t.modelNameModelCondition().forUpdate();
                    }
                                
                    public #t.modelNameModelCondition forDelete() {
                        return new #t.modelNameModelCondition().forDelete();
                    }
                                
                    public #t.modelNameModelCondition forSelect() {
                        return new #t.modelNameModelCondition().forSelect();
                    }
                                
                    public #t.modelNameModelCondition forCount() {
                        return forSelect().id().count();
                    }
                                
                    public class #t.modelNameModelCondition extends Condition {
                        #t.modelNameModelCondition parent = null;
                                
                        private #t.modelNameModelCondition() {
                        }
                                
                        private #t.modelNameModelCondition(#t.modelNameModelCondition condition) {
                            this.parent = condition;
                        }
                                
                        private #t.modelNameModelCondition forInsert() {
                            #t.modelNameModelCondition condition = new #t.modelNameModelCondition();
                            List<String> columnNameList = new ArrayList<>();
                            List<String> valueList = new ArrayList<>();
                /* append $modelForInsertFieldAppender$ */
                            condition.getValueList().add(LocalTool.getUserId());
                            condition.getValueList().add(LocalTool.getUserId());
                            condition.getValueList().add(LocalDateTime.now());
                            condition.getValueList().add(LocalDateTime.now());
                            condition.setSql("INSERT INTO #t.tableName(%s, create_by, update_by, create_time, update_time) VALUES (%s, ?, ?, ?, ?)".formatted(
                                    String.join(", ", columnNameList),
                                    String.join(", ", valueList)
                            ));
                            return condition;
                        }
                                
                        private #t.modelNameModelCondition forUpdate() {
                            #t.modelNameModelCondition condition = new #t.modelNameModelCondition();
                /* append $modelForUpdateFieldAppender$ */
                            condition.getUpdateList().add("update_by = ?");
                            condition.getUpdateValueList().add(LocalTool.getUserId());
                            condition.getUpdateList().add("update_time = ?");
                            condition.getUpdateValueList().add(LocalDateTime.now());
                            condition.setSql("UPDATE #t.tableName#update##where##order##limit#");
                            return condition;
                        }
                                
                        private #t.modelNameModelCondition forDelete() {
                            #t.modelNameModelCondition condition = new #t.modelNameModelCondition();
                            condition.setSql("DELETE FROM #t.tableName#where##group##order##limit#");
                            return condition;
                        }
                                
                        private #t.modelNameModelCondition forSelect() {
                            #t.modelNameModelCondition condition = new #t.modelNameModelCondition();
                            condition.modelClass = #t.modelName.class;
                            condition.setSql("SELECT #select# FROM #t.tableName#where##group##order##limit#");
                            return condition;
                        }
                                
                        public #t.modelNameModelCondition distinct() {
                            this.distinct = true;
                            return this;
                        }
                                
                        public #t.modelNameModelCondition limit(int limit) {
                            this.limit = " LIMIT " + limit;
                            return this;
                        }
                                
                        public #t.modelNameModelCondition sub() {
                            return new #t.modelNameModelCondition(this);
                        }
                                
                        public #t.modelNameModelCondition finish() {
                            if (!whereList.isEmpty()) {
                                parent.whereList.add("(" + String.join(" OR ", whereList) + ")");
                            }
                            parent.whereValueList.addAll(whereValueList);
                            return parent;
                        }
                        
                        public #t.modelNameCondition toFlex() {
                            #t.modelNameCondition flex = new #t.modelNameCondition();
                            flex.setSql(sql);
                            flex.setDistinct(distinct);
                            flex.setModelClass(modelClass);
                            flex.setSelectList(selectList);
                            flex.setUpdateList(updateList);
                            flex.setUpdateValueList(updateValueList);
                            flex.setWhereList(whereList);
                            flex.setWhereValueList(whereValueList);
                            flex.setGroupList(groupList);
                            flex.setOrderList(orderList);
                            flex.setLimit(limit);
                            return flex;
                        }
                                
                /* append $modelConditionFieldAppender$ */
                                
                        public Sql sql() {
                            return new Sql();
                        }
                        
                        public class Sql {
                            private Sql() {
                            }
                            
                            public #t.modelNameModelCondition select(String sql) {
                                #t.modelNameModelCondition.this.getSelectList().add(sql);
                                return #t.modelNameModelCondition.this;
                            }
                            
                            public #t.modelNameModelCondition update(String sql) {
                                #t.modelNameModelCondition.this.getUpdateList().add(sql);
                                return #t.modelNameModelCondition.this;
                            }
                            
                            public #t.modelNameModelCondition update(String sql, Object... values) {
                                if (values != null && values.length > 0) {
                                    #t.modelNameModelCondition.this.getUpdateList().add(sql);
                                    #t.modelNameModelCondition.this.getUpdateValueList().addAll(Arrays.asList(values));
                                }
                                return #t.modelNameModelCondition.this;
                            }
                            
                            public #t.modelNameModelCondition where(String sql) {
                                #t.modelNameModelCondition.this.getWhereList().add(sql);
                                return #t.modelNameModelCondition.this;
                            }
                            
                            public #t.modelNameModelCondition where(String sql, Object... values) {
                                if (values != null && values.length > 0) {
                                    #t.modelNameModelCondition.this.getWhereList().add(sql);
                                    #t.modelNameModelCondition.this.getWhereValueList().addAll(Arrays.asList(values));
                                }
                                return #t.modelNameModelCondition.this;
                            }
                            
                            public #t.modelNameModelCondition group(String sql) {
                                #t.modelNameModelCondition.this.getGroupList().add(sql);
                                return #t.modelNameModelCondition.this;
                            }
                            
                            public #t.modelNameModelCondition order(String sql) {
                                #t.modelNameModelCondition.this.getOrderList().add(sql);
                                return #t.modelNameModelCondition.this;
                            }
                            
                        }
                                
                    }
                }
                """;


        save(buildData,
                "#c.javaPath\\src\\main\\java\\top\\chmin\\project\\cloud\\#t.modulePath\\#t.modelName.java",
                source
        );

    }
}
